/***************************************************************************
* Copyright (C) 2012, Chain Studios.
*
* This file is part of QeffectsGL source code.
*
* QeffectsGL source code is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* QeffectsGL source code is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
***************************************************************************/
#include "qfx_library.h"
#include "qfx_log.h"
#include "qfx_settings.h"

//=========================================
// QFXSettings class implementation
//-----------------------------------------
// Load settings from INI file
//=========================================

//provide Windows-like functions for ini-file parsing
#ifdef __linux__
static size_t GetPrivateProfileString(const char* app, const char* setting, const char* defaultValue, char* outBuf, size_t outSize, const char* fileName)
{
    const size_t bufSize = 256;
    FILE* iniFile = fopen(fileName, "r");
    char buffer[bufSize];
    if (iniFile != NULL)
    {
        while (true)
        {
            char* p = fgets(buffer, bufSize, iniFile);
            if (!feof(iniFile) && p != NULL)
            {
                size_t consumed = strcspn(buffer, "[");
                if (consumed != strlen(buffer))
                {
                    char* appBuf = buffer + consumed + 1;
                    consumed = strcspn(appBuf, "]");

                    if (consumed != strlen(appBuf))
                    {
                        appBuf[consumed] = '\0';

                        if (strcmp(app, appBuf) == 0)
                        {
                            while (true)
                            {
                                char* p = fgets(buffer, bufSize, iniFile);
                                if (!feof(iniFile) && p != NULL &&  buffer[0] != '\0')
                                {
                                    char* keyBuf = buffer;
                                    consumed = strcspn(buffer, "=");
                                    if (consumed != strlen(buffer))
                                    {
                                        keyBuf[consumed] = '\0';

                                        if (strcmp(setting, keyBuf) == 0)
                                        {
                                            char* valBuf = buffer + consumed + 1;

                                            size_t valLen = strlen(valBuf);
                                            if (valBuf[valLen-1] == '\n')
                                            {
                                                valBuf[valLen-1] = '\0';
                                                valLen--;
                                            }

                                            if (valLen > outSize - 1 )
                                            {
                                                strncpy(outBuf, valBuf, outSize - 1);
                                                outBuf[outSize - 1] = '\0';
                                                fclose(iniFile);
                                                return outSize-1;
                                            }
                                            else
                                            {
                                                strcpy(outBuf, valBuf);
                                                fclose(iniFile);
                                                return valLen;
                                            }
                                        }

                                    }
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                break;
            }
        }
    }
    else
        printf("Can't read file");

    if (defaultValue != NULL)
        strcpy(outBuf, defaultValue);
    else
        outBuf[0] = '\0';
    fclose(iniFile);
    return 0;
}

static int GetPrivateProfileInt(const char* app, const char* setting, int defaultValue, const char* fileName)
{
    char buffer[32];
    GetPrivateProfileString(app, setting, NULL, buffer, 32, fileName);
    int value = atoi(buffer);
    if (value == 0 && (buffer[0] != '0'))
        return defaultValue;
    return value;
}

#endif

QFXSettings :: QFXSettings()
{
    #ifdef _WIN32
	// get current executable name
	if (!GetModuleFileName( NULL, m_szExeName, sizeof(m_szExeName)-1 )) {
		m_szExeName[0] = 0;
	}

	if ( m_szExeName[1] != ':' ) {
		// not a full path, assume current directory for INI
		GetCurrentDirectory( sizeof(m_szIniFile)-1, m_szIniFile );
		strcat_s( m_szIniFile, "\\" QFX_LIBRARY_TITLE ".ini" );

	} else {
		// full path, assume its directory for INI
		strcpy_s( m_szIniFile, m_szExeName );
		size_t l = strlen( m_szIniFile );
		for ( size_t i = l - 1; i > 0; i-- ) {
			if ( m_szIniFile[i] == '\\' || m_szIniFile[i] == '/' ) {
				m_szIniFile[i] = 0;
				break;
			}
		}
		strcat_s( m_szIniFile, "\\" QFX_LIBRARY_TITLE ".ini" );
	}

	char *p1 = strrchr( m_szExeName, '\\' );
	char *p2 = strrchr( m_szExeName, '/' );
	char *p = p1 > p2 ? p1 : p2;
	if ( p )
		strncpy_s( m_szExeName, p + 1, strlen( p + 1 ) );

    #elif defined __linux__

    int len = readlink("/proc/self/exe", m_szExeName, MAX_PATH-1);
    if (len <= 0)
    {
        m_szExeName[0] = '\0';
    }
    else
    {
        m_szExeName[len] = '\0';
        char* p = strrchr( m_szExeName, '/' );

        if ( p )
        {
            p++;
            strcpy(m_szExeName, p);
        }

        //remove extension and add .exe
        size_t consumed = strcspn(m_szExeName, ".");
        m_szExeName[consumed] = '\0';
        strcat(m_szExeName, ".exe");

    }

    char* homePath = getenv("HOME");
    if (homePath != NULL)
    {
        strcpy(m_szIniFile, homePath);
        strcat(m_szIniFile, "/.config/" QFX_LIBRARY_TITLE "/" QFX_LIBRARY_TITLE ".ini");
    }
    else
    {
        m_szIniFile[0] = '\0';
    }

    #else
        #error Unsupported platform
    #endif

	QFXLog::Instance().Printf("Settings: %s\n", m_szIniFile);
	QFXLog::Instance().Printf("Module: %s\n", m_szExeName);
}

QFXSettings :: ~QFXSettings()
{
}

int QFXSettings :: GetInteger( const char *setting, int defaultValue )
{
	int value = GetPrivateProfileInt( m_szExeName, setting, -99999, m_szIniFile );
	if ( value == -99999 )
		return GetPrivateProfileInt( "Generic", setting, defaultValue, m_szIniFile );
	else
		return value;
}

float QFXSettings :: GetFloat( const char *setting, float defaultValue )
{
	char buffer[32];
	GetPrivateProfileString( m_szExeName, setting, NULL, buffer, sizeof(buffer)-1, m_szIniFile );
	if ( !strlen( buffer ) ) {
		GetPrivateProfileString( "Generic", setting, NULL, buffer, sizeof(buffer)-1, m_szIniFile );
		if ( !strlen( buffer ) )
			return defaultValue;
	}
	return (float)atof( buffer );
}

bool QFXSettings :: CheckEXE( const char *s )
{
    #ifdef _WIN32
	if ( !_stricmp( m_szExeName, s ) )
		return true;
    #elif defined __linux__
        if ( !strcmp( m_szExeName, s ) )
		return true;
    #endif
	return false;
}
